#include "fontmaterial.h"
#include "log.h"

FT_Library m_FTLib;

void InitFreeTypeLibrary()
{
	
	Log::Debug( "Initializing FreeType" );
	
	FT_Init_FreeType( &m_FTLib );
	
}

void CleanFreeTypeLibrary()
{

	FT_Done_FreeType( m_FTLib );
	
}

CFontMaterial::~CFontMaterial()
{
	
	if( m_Textures )
		glDeleteLists( m_DList, 256 );
	
	glDeleteTextures( 256, m_Textures );
	
	if( m_XTrans )
		delete [] m_XTrans;
	
	if( m_FontCharacters )
		delete [] m_FontCharacters;
	
}

void CFontMaterial::Draw( std::string text, double x, double y )
{
	
	PUSH_MATRIX;
	
		Draw::Translate( x, y + m_Height, 0.0f );
		
		for( int j = 0; j < text.length(); j++ )
			DrawCharacter( text[j] );
			
	POP_MATRIX;
	
	Draw::SetSTMul( 1.0f, 1.0f );
	
}

void CFontMaterial::DrawCharacter( char c )
{
	
	Draw::BindTexture( m_Textures[c] );
		
	PUSH_MATRIX;

	Draw::Translate( m_FontCharacters[c].m_Left, m_FontCharacters[c].m_Down - m_FontCharacters[c].m_Size.y, 0.0f );
	Draw::Scale( m_FontCharacters[c].m_Size.x, m_FontCharacters[c].m_Size.y, 1.0f );
	Draw::SetSTMul( m_FontCharacters[c].m_CoordMul.x, m_FontCharacters[c].m_CoordMul.y );
	Draw::RawQuad();
		
	POP_MATRIX;
		
	Draw::Translate( m_XTrans[c], 0.0f, 0.0f );
	
}

void CFontMaterial::LoadFromFile( std::string file )
{
	
	m_Tag = file;
	
	Log::Debug( "Loading font: " + file );
	
	if( !Util::DoesFileExist( file.c_str() ) )
	{
		
		Log::Debug( "ERROR This font file can not be found!" );
		return;
		
	}
	
	FT_Face face;
	
	FT_New_Face( m_FTLib, file.c_str(), 0, &face );
	
	FT_Set_Pixel_Sizes( face, 0, m_Height );
	
	m_Textures = new GLuint[256];
	
	glGenTextures( 256, m_Textures );
	m_DList = glGenLists( 256 );
	
	m_FontCharacters = new CFontCharacter[256];
	m_XTrans = new int[256];
	
	for( int j = 0; j < 256; j++ )
	{
		
		FT_UInt glyphindex = FT_Get_Char_Index( face, j );
		FT_Load_Glyph( face, glyphindex, FT_LOAD_RENDER );
		FT_GlyphSlot slot = face->glyph;
		FT_Bitmap bitmap = slot->bitmap;
		
		int down = ( slot->metrics.height - slot->metrics.horiBearingY ) >> 6;
		
		int w = Util::RoundToPower( bitmap.width, 2 );
		int h = Util::RoundToPower( bitmap.rows, 2 );
		
		GLubyte * data = new GLubyte[2 * w * h];
		
		for( int y = 0; y < bitmap.rows; y++ )
		{
			
			for( int x = 0; x < bitmap.width; x++ )
			{
				
				data[2 * ( x + y * w )] = 255;
				data[2 * ( x + y * w ) + 1] = bitmap.buffer[x + bitmap.width * y];
				
			}
			
		}
		
		glBindTexture( GL_TEXTURE_2D, m_Textures[j] );
		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
		
		glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data );
		
		m_FontCharacters[j].m_CoordMul.SetXY( ( float )bitmap.width / ( float )w, ( float )bitmap.rows / ( float )h );
		m_FontCharacters[j].m_Trans = face->glyph->advance.x >> 6;
		m_FontCharacters[j].m_Left = face->glyph->bitmap_left;
		m_FontCharacters[j].m_Size.SetXY( bitmap.width, bitmap.rows );
		m_FontCharacters[j].m_Down = down;
		
		delete [] data;
		
		
		
		m_XTrans[j] = m_FontCharacters[j].m_Trans;
		
		
	}
	
	FT_Done_Face( face );
	
	
}